home *** CD-ROM | disk | FTP | other *** search
Text File | 2000-10-06 | 13.4 KB | 724 lines | [TEXT/CWIE] |
- ///--------------------------------------------------------------------------------------
- // BlitPixieDirtyRects - zero overdraw screen blitter
- //
- // The idea is to divide the screen into small 32x1 "dirty rects".
- // A bitmap keeps track of which rects are "dirty" and thus need updating.
- // User needs to add all areas that have changed since last blit.
- //
- // NOTE: Call BlitPixieInitDirtyRects before using, or you will crash.
- //
- // written by Anders F Björklund <afb@algonet.se>
- // ©2000 afb.
- ///--------------------------------------------------------------------------------------
-
- #ifndef __BLITPIXIE__
- #include "BlitPixieHeader.h"
- #endif
-
- #include "BlitPixieAsm.h"
-
- ///--------------------------------------------------------------------------------------
- // Some conditional macros
- ///--------------------------------------------------------------------------------------
-
- // LOCAL :
- #if GENERATINGASM
- #define LOCAL extern // generate "extern" references for asm
- #elif (USE_ASSEMBLY || USE_GENERIC_C)
- #define LOCAL static // if we are using inline functions we can use "static"
- #if USE_PPC_ASSEMBLY
- #pragma toc_data on // store static data in TOC directly
- #endif
- #else
- #define LOCAL // if using separate functions, we need global to link
- #endif
-
- // MALLOC,FREE :
- #if macintosh
- #include <Memory.h>
- #define MALLOC(s) (void *) NewPtr( s )
- #define FREE(p) DisposePtr( (Ptr) p )
- #else
- #include <stdlib.h>
- #define MALLOC(s) malloc(s)
- #define FREE(p) free(p)
- #endif
-
- ///--------------------------------------------------------------------------------------
- // Local variables that store dirty rect variables
- ///--------------------------------------------------------------------------------------
-
- LOCAL unsigned char *matrixDirtyBits; // bitmap dirty matrix ( 1 bit = 32x1 pixels)
-
- LOCAL unsigned short matrixWidth; // width (pixels)
- LOCAL unsigned short matrixHeight; // height (pixels)
- LOCAL unsigned short matrixDepth; // bits per pixel
-
- LOCAL unsigned short matrixBytes; // bytes (of screen pixels)
- LOCAL unsigned short matrixRows; // rows
- LOCAL unsigned short matrixShift; // bit positions (in depth)
- LOCAL unsigned short matrixBits; // pixel blocks of 32 bytes - matrix bits
- LOCAL unsigned long matrixRowBytes; // bytes per row (in matrix)
-
- ///--------------------------------------------------------------------------------------
-
- #pragma mark *** PowerPC asm:
- #if USE_PPC_ASSEMBLY
-
- ASM_FUNC void BlitPixieBlitClearDirtyRects(
- register unsigned char *src, // r3
- register unsigned char *dst, // r4
- register unsigned long color, // r5
- register unsigned long srcBytes, // r6
- register unsigned long dstBytes) // r7
- {
- #define r_src r3
- #define r_dst r4
- #define r_color r5
- #define r_srcBytes r6
- #define r_dstBytes r7
-
- #define r_dirty r8
- #define r_rows r10
- #define r_rowBytes r11
- #define r_save r12
-
- ASM_BEGIN
-
- lwz r_dirty,matrixDirtyBits(RTOC)
- lhz r_rows,matrixRows(RTOC)
- lwz r_rowBytes,matrixRowBytes(RTOC)
-
- // double background pixels (long->double)
- stw r_color,-8(SP)
- stw r_color,-4(SP)
-
- dcbt r0,r_dirty
-
- // calculate stride from matrixRowBytes ( 8 bits per byte, 32 pixel bytes per bit)
- rlwinm r0,r_rowBytes,8,0,31-8
- mfcr r_save
-
- sub r_srcBytes,r_srcBytes,r0
- sub r_dstBytes,r_dstBytes,r0
-
- lfd fp0,-8(SP)
- subi r_dirty,r_dirty,1
-
- li r0,0
- @rowloop:
-
- mtctr r_rowBytes
-
- #define MOVE_COND_32(i) \
- bc IF_NOT,24+i,@skip##i; \
- lfd fp1,i*32+0(r3); \
- lfd fp2,i*32+8(r3); \
- lfd fp3,i*32+16(r3); \
- lfd fp4,i*32+24(r3); \
- stfd fp0,i*32+0(r3); \
- stfd fp0,i*32+8(r3); \
- stfd fp0,i*32+16(r3); \
- stfd fp0,i*32+24(r3); \
- stfd fp1,i*32+0(r4); \
- stfd fp2,i*32+8(r4); \
- stfd fp3,i*32+16(r4); \
- stfd fp4,i*32+24(r4); \
- @skip##i:
-
- @byteloop:
- lbzu r9,1(r_dirty)
- cmplwi r9,0
- beq @skipbyte
-
- mtcrf 0xFF,r9
- stb r0,-1(r_dirty) // clear matrix for next time
-
- MOVE_COND_32(0)
- MOVE_COND_32(1)
- MOVE_COND_32(2)
- MOVE_COND_32(3)
- MOVE_COND_32(4)
- MOVE_COND_32(5)
- MOVE_COND_32(6)
- MOVE_COND_32(7)
- @skipbyte:
-
- addi r3,r3,8*32
- addi r4,r4,8*32
-
- bdnz @byteloop
-
- #undef MOVE_COND_32
-
- subic. r_rows,r_rows,1
-
- add r3,r3,r_srcBytes
- add r4,r4,r_dstBytes
-
- bne @rowloop
-
- mtcrf 0xFF,r_save
-
- ASM_END
- }
-
- ASM_FUNC void BlitPixieBlitEraseDirtyRects(
- register unsigned char *src, // r3
- register unsigned char *dst, // r4
- register unsigned char *bkg, // r5
- register unsigned long srcBytes, // r6
- register unsigned long dstBytes) // r7
- {
- #define r_src r3
- #define r_dst r4
- #define r_bkg r5
- #define r_srcBytes r6
- #define r_dstBytes r7
-
- #define r_dirty r8
- #define r_rows r10
- #define r_rowBytes r11
- #define r_save r12
-
- ASM_BEGIN
-
- lwz r_dirty,matrixDirtyBits(RTOC)
- lhz r_rows,matrixRows(RTOC)
- lwz r_rowBytes,matrixRowBytes(RTOC)
-
- dcbt r0,r_dirty
-
- // calculate stride from matrixRowBytes ( 8 bits per byte, 32 pixel bytes per bit)
- rlwinm r0,r_rowBytes,8,0,31-8
- mfcr r_save
-
- sub r_srcBytes,r_srcBytes,r0
- sub r_dstBytes,r_dstBytes,r0
-
- subi r_dirty,r_dirty,1
-
- li r0,0
- @rowloop:
-
- mtctr r_rowBytes
-
- #define MOVE_COND_32(i) \
- bc IF_NOT,24+i,@skip##i; \
- lfd fp1,i*32+0(r5); \
- lfd fp2,i*32+8(r5); \
- lfd fp3,i*32+16(r5); \
- lfd fp4,i*32+24(r5); \
- lfd fp5,i*32+0(r3); \
- lfd fp6,i*32+8(r3); \
- lfd fp7,i*32+16(r3); \
- lfd fp8,i*32+24(r3); \
- stfd fp1,i*32+0(r3); \
- stfd fp2,i*32+8(r3); \
- stfd fp3,i*32+16(r3); \
- stfd fp4,i*32+24(r3); \
- stfd fp5,i*32+0(r4); \
- stfd fp6,i*32+8(r4); \
- stfd fp7,i*32+16(r4); \
- stfd fp8,i*32+24(r4); \
- @skip##i:
-
- @byteloop:
- lbzu r9,1(r_dirty)
- cmplwi r9,0
- beq @skipbyte
-
- mtcrf 0xFF,r9
- stb r0,-1(r_dirty) // clear matrix for next time
-
- MOVE_COND_32(0)
- MOVE_COND_32(1)
- MOVE_COND_32(2)
- MOVE_COND_32(3)
- MOVE_COND_32(4)
- MOVE_COND_32(5)
- MOVE_COND_32(6)
- MOVE_COND_32(7)
- @skipbyte:
-
- addi r3,r3,8*32
- addi r4,r4,8*32
- addi r5,r5,8*32
-
- bdnz @byteloop
-
- #undef MOVE_COND_32
-
- subic. r_rows,r_rows,1
-
- add r3,r3,r_srcBytes
- add r4,r4,r_dstBytes
- add r5,r5,r_srcBytes
-
- bne @rowloop
-
- mtcrf 0xFF,r_save
-
- ASM_END
- }
-
- #pragma mark *** 680X0 asm :
- #elif USE_68K_ASSEMBLY
-
- ASM_FUNC void BlitPixieBlitClearDirtyRects(
- unsigned char *src, // A0
- unsigned char *dst, // A1
- unsigned long color, // D0
- unsigned long srcBytes, // D2
- unsigned long dstBytes) // D3
- {
- ASM_BEGIN
-
- MOVEM.L D3-D7/A2,-(SP)
-
- MOVEM.L src,A0/A1
- MOVEM.L srcBytes,D2-D3
- CLR.L D4
- CLR.L D5
-
- MOVEA.L matrixDirtyBits,A2
- MOVE.L matrixRowBytes,D4
- MOVE.W matrixRows,D5
-
- MOVE.L D4,D0
- LSL.L #8,D0
- SUB.L D0,D2
- SUB.L D0,D3
-
- SUBQ.W #1,D4
- SUBQ.W #1,D5
-
- MOVE.L color,D0
- CLR.L D1
- MOVEQ #32,D7
-
- @rowloop:
-
- MOVE.W D4,D6
-
- #define MOVE_COND_32(i) \
- LSL.B #1,D1; \
- BCC.S @skip##i; \
- MOVE.L (A0),(A1)+; \
- MOVE.L D0,(A0)+; \
- MOVE.L (A0),(A1)+; \
- MOVE.L D0,(A0)+; \
- MOVE.L (A0),(A1)+; \
- MOVE.L D0,(A0)+; \
- MOVE.L (A0),(A1)+; \
- MOVE.L D0,(A0)+; \
- MOVE.L (A0),(A1)+; \
- MOVE.L D0,(A0)+; \
- MOVE.L (A0),(A1)+; \
- MOVE.L D0,(A0)+; \
- MOVE.L (A0),(A1)+; \
- MOVE.L D0,(A0)+; \
- MOVE.L (A0),(A1)+; \
- MOVE.L D0,(A0)+; \
- BRA.S @end##i; \
- @skip##i: \
- ADDA.L D7,A0; \
- ADDA.L D7,A1; \
- @end##i:
-
- @byteloop:
- MOVE.B (A2),D1
- BEQ @skipbyte
- CLR.B (A2)+ // clear matrix for next time
-
- MOVE_COND_32(0)
- MOVE_COND_32(1)
- MOVE_COND_32(2)
- MOVE_COND_32(3)
- MOVE_COND_32(4)
- MOVE_COND_32(5)
- MOVE_COND_32(6)
- MOVE_COND_32(7)
-
- DBRA D6,@byteloop
- BRA @nextrow
-
- #undef MOVE_COND_32
-
- @skipbyte:
- MOVE.B #32*8-1,D1
- ADDA.L D1,A0
- ADDA.L D1,A1
- ADDQ.L #1,A0
- ADDQ.L #1,A1
- ADDQ.L #1,A2
-
- DBRA D6,@byteloop
-
- @nextrow:
- ADDA.L D2,A0
- ADDA.L D3,A1
-
- DBRA D5,@rowloop
-
- MOVEM.L (SP)+,D3-D7/A2
-
- ASM_END
- }
-
- ASM_FUNC void BlitPixieBlitEraseDirtyRects(
- unsigned char *src,
- unsigned char *dst,
- unsigned char *bkg,
- unsigned long srcBytes,
- unsigned long dstBytes)
- {
- ASM_BEGIN
-
- MOVEM.L D3-D7/A2-A3,-(SP)
-
- MOVEM.L src,A0-A2
- MOVEM.L srcBytes,D2-D3
- CLR.L D4
- CLR.L D5
-
- MOVEA.L matrixDirtyBits,A3
- MOVE.L matrixRowBytes,D4
- MOVE.W matrixRows,D5
-
- MOVE.L D4,D0
- LSL.L #8,D0
- SUB.L D0,D2
- SUB.L D0,D3
-
- SUBQ.W #1,D4
- SUBQ.W #1,D5
-
- CLR.L D1
- MOVEQ #32,D7
-
- @rowloop:
-
- MOVE.W D4,D6
-
- #define MOVE_COND_32(i) \
- LSL.B #1,D1; \
- BCC.S @skip##i; \
- MOVE.L (A0),(A1)+; \
- MOVE.L (A2)+,(A0)+; \
- MOVE.L (A0),(A1)+; \
- MOVE.L (A2)+,(A0)+; \
- MOVE.L (A0),(A1)+; \
- MOVE.L (A2)+,(A0)+; \
- MOVE.L (A0),(A1)+; \
- MOVE.L (A2)+,(A0)+; \
- MOVE.L (A0),(A1)+; \
- MOVE.L (A2)+,(A0)+; \
- MOVE.L (A0),(A1)+; \
- MOVE.L (A2)+,(A0)+; \
- MOVE.L (A0),(A1)+; \
- MOVE.L (A2)+,(A0)+; \
- MOVE.L (A0),(A1)+; \
- MOVE.L (A2)+,(A0)+; \
- BRA.S @end##i; \
- @skip##i: \
- ADDA.L D7,A0; \
- ADDA.L D7,A1; \
- ADDA.L D7,A2; \
- @end##i:
-
- @byteloop:
- MOVE.B (A3),D1
- BEQ @skipbyte
- CLR.B (A3)+ // clear matrix for next time
-
- MOVE_COND_32(0)
- MOVE_COND_32(1)
- MOVE_COND_32(2)
- MOVE_COND_32(3)
- MOVE_COND_32(4)
- MOVE_COND_32(5)
- MOVE_COND_32(6)
- MOVE_COND_32(7)
-
- DBRA D6,@byteloop
- BRA @nextrow
-
- #undef MOVE_COND_32
-
- @skipbyte:
- MOVE.B #32*8-1,D1
- ADDA.L D1,A0
- ADDA.L D1,A1
- ADDA.L D1,A2
- ADDQ.L #1,A0
- ADDQ.L #1,A1
- ADDQ.L #1,A2
- ADDQ.L #1,A3
-
- DBRA D6,@byteloop
-
- @nextrow:
- ADDA.L D2,A0
- ADDA.L D3,A1
- ADDA.L D2,A2
-
- DBRA D5,@rowloop
-
- MOVEM.L (SP)+,D3-D7/A2-A3
-
- ASM_END
- }
-
- #pragma mark *** Generic C :
- #elif USE_GENERIC_C
-
- void BlitPixieBlitClearDirtyRects(
- unsigned char *src,
- unsigned char *dst,
- unsigned long color,
- unsigned long srcBytes,
- unsigned long dstBytes)
- {
- int x,y;
- unsigned char *p,*row;
- unsigned int c,m;
-
- srcBytes -= matrixBytes;
- dstBytes -= matrixBytes;
-
- row = matrixDirtyBits;
- for ( y = 0; y < matrixRows; y++ )
- {
- p = row;
- m = 0;
-
- for ( x = 0; x < matrixBits; x++ )
- {
- if ( m == 0 )
- {
- m = 0x80;
- c = *p;
- *p++ = 0;
- }
-
- if ( c & m )
- {
- // copy offscreen->screen
- BlitPixieMemCopy( dst, src, 32 );
- // clear offscreen
- BlitPixieMemSet( src, color, 32 );
- }
-
- src += 32;
- dst += 32;
-
- m >>= 1;
- }
-
- src += srcBytes;
- dst += dstBytes;
-
- row += matrixRowBytes;
- }
- }
-
- void BlitPixieBlitEraseDirtyRects(
- unsigned char *src,
- unsigned char *dst,
- unsigned char *bkg,
- unsigned long srcBytes,
- unsigned long dstBytes)
- {
- int x,y;
- unsigned char *p,*row;
- unsigned int c,m;
-
- srcBytes -= matrixBytes;
- dstBytes -= matrixBytes;
-
- row = matrixDirtyBits;
- for ( y = 0; y < matrixRows; y++ )
- {
- p = row;
- m = 0;
-
- for ( x = 0; x < matrixBits; x++ )
- {
- if ( m == 0 )
- {
- m = 0x80;
- c = *p;
- *p++ = 0;
- }
-
- if ( c & m )
- {
- // copy offscreen->screen
- BlitPixieMemCopy( dst, src, 32 );
- // erase offscreen
- BlitPixieMemCopy( src, bkg, 32 );
- }
-
- src += 32;
- dst += 32;
- bkg += 32;
-
- m >>= 1;
- }
-
- src += srcBytes;
- dst += dstBytes;
- bkg += srcBytes;
-
- row += matrixRowBytes;
- }
- }
-
- #endif
-
- #pragma mark -
- // ————————————————————————————————————————————————————————————————————————————————
-
- #ifndef GENERATINGASM // do not include for asm file generation
-
- Boolean BlitPixieInitDirtyRects( unsigned char *src, unsigned char *dst,
- unsigned short width, unsigned short height, unsigned short depth )
- {
- long bytes;
-
- bytes = ( width * depth ) >> 3;
-
- if ( depth != 8 && depth != 16 && depth != 32 )
- {
- BLITPIXIE_DEBUGGER("DirtyRects: depth must be 8, 16 or 32");
- return false;
- }
-
- if ( (bytes & 31) != 0 )
- {
- BLITPIXIE_DEBUGGER("DirtyRects: bytes must be multiple of 32");
- return false;
- }
-
- if ( (((unsigned long) src) & 3) != 0 || (((unsigned long) dst) & 3) != 0)
- {
- BLITPIXIE_DEBUGGER("DirtyRects: src and dst must be aligned");
- return false;
- }
-
- matrixWidth = width;
- matrixHeight = height;
- matrixDepth = depth;
-
- matrixBytes = bytes;
- matrixRows = height;
-
- matrixShift = matrixDepth >> 4;
- matrixBits = matrixBytes >> 5;
- matrixRowBytes = (matrixBits + 7) >> 3;
-
- matrixDirtyBits = (unsigned char *) MALLOC(matrixRowBytes * matrixRows);
- if ( matrixDirtyBits == NULL )
- {
- BLITPIXIE_DEBUGGER("DirtyRects: Couldn't get dirty matrix mem!");
- return false;
- }
-
- BlitPixieClearDirtyRects();
- BlitPixieAddDirtyRect( (Rect*) NULL );
-
- return true;
- }
-
-
- void BlitPixieExitDirtyRects(void)
- {
- if ( matrixDirtyBits )
- {
- FREE(matrixDirtyBits);
- matrixDirtyBits = NULL;
- }
- }
-
-
- void BlitPixieAddDirtyRect( Rect *dirtyRect )
- {
- long top,left,bottom,right;
- long startBit,stopBit;
- long y,bit,grid;
- unsigned char *row,*p;
- unsigned char m;
-
- if ( dirtyRect != NULL )
- {
- top = dirtyRect->top;
- left = dirtyRect->left;
- bottom = dirtyRect->bottom;
- right = dirtyRect->right;
-
- // align to 32-byte grid
- grid = 32 >> matrixShift;
- left = (left) & ~(grid - 1);
- right = (right + grid - 1) & ~(grid - 1);
-
- // clip
- if ( left < 0 ) left = 0;
- if ( top < 0 ) top = 0;
- if ( right >= matrixWidth ) right = matrixWidth - 1;
- if ( bottom >= matrixHeight ) bottom = matrixHeight - 1;
-
- // check for empty/clipped rect
- if ( left >= right ) return;
- if ( top >= bottom ) return;
- }
- else
- {
- // add whole area
- left = 0;
- top = 0;
- right = matrixWidth - 1;
- bottom = matrixHeight - 1;
- }
-
- // pixels to bytes
- left <<= matrixShift;
- right <<= matrixShift;
-
- // calculate bit mask
- startBit = left >> 5;
- stopBit = right >> 5;
-
- // add to dirty matrix (set bits)
- y = bottom - top;
- row = matrixDirtyBits + (top * matrixRowBytes);
- while (y--)
- {
- p = row + (startBit >> 3);
- m = 0x80U >> (startBit & 7);
-
- for ( bit = startBit; bit <= stopBit; bit++ )
- {
- *p |= m;
-
- m >>= 1;
- if ( m == 0)
- {
- p++;
- m = 0x80U;
- }
- }
- row += matrixRowBytes;
- }
-
- }
-
- void BlitPixieClearDirtyRects( void )
- {
- // clear all bits in dirty matrix
- BlitPixieMemSet(matrixDirtyBits,0L, matrixRowBytes * matrixRows);
- }
-
-
- #endif // GENERATINGASM
-